package com.cockatiel.statemachine.spring.statemachine.config;

import com.cockatiel.statemachine.enums.ActivityEvent;
import com.cockatiel.statemachine.enums.ActivityState;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;

import java.util.EnumSet;

/**
 * 状态机配置类
 *
 * @Author: louxiujun@kanzhun.com
 * @Date: 2023-06-10 21:42:23
 * @Description:
 */
@Configuration
@EnableStateMachine
@Slf4j
public class ActivityStatemachineConfigurer extends EnumStateMachineConfigurerAdapter<ActivityState, ActivityEvent> {

    // 设置状态机的初始状态
    @Override
    public void configure(StateMachineStateConfigurer<ActivityState, ActivityEvent> states) throws Exception {
        states.withStates().initial(ActivityState.NOT_START).states(EnumSet.allOf(ActivityState.class));
    }

    // 设置状态机的流转规则
    @Override
    public void configure(StateMachineTransitionConfigurer<ActivityState, ActivityEvent> transitions) throws Exception {
        transitions.withExternal()
                .source(ActivityState.NOT_START)
                .target(ActivityState.DATA_PREPARING)
                .event(ActivityEvent.ACT_BEGIN)
                .action(notice())
                .and()
                .withExternal()
                .source(ActivityState.DATA_PREPARING)
                .target(ActivityState.DATA_PREPARED)
                .event(ActivityEvent.FINISH_DATA_CAL)
                .action(notice())
                .and()
                .withExternal()
                .source(ActivityState.DATA_PREPARED)
                .target(ActivityState.DATA_PUSHING)
                .event(ActivityEvent.FINISH_DATA_PREPARE)
                .action(notice())
                .and()
                .withExternal()
                .source(ActivityState.DATA_PUSHING)
                .target(ActivityState.FINISHED)
                .event(ActivityEvent.FINISH_DATA_PUSHING)
                .action(notice())
                .and();
    }

    // 设置状态机的名称
    @Override
    public void configure(StateMachineConfigurationConfigurer<ActivityState, ActivityEvent> config) throws Exception {
        config.withConfiguration().machineId("ActivityStateMachine");
    }

    // Mock消息通知
    public Action<ActivityState, ActivityEvent> notice() {
        return context -> log.info("【变更前状态】:" + context.getSource().getId() + ";【变更后状态】:" + context.getTarget().getId());
    }
}
